//获取画布接口
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var gnav = document.getElementById("gnav")
var mine_total = document.getElementById('mine-total')

/**初始化游戏信息变量 */
var levels = [[9, 9, 10], [16, 16, 40], [16, 30, 99]]

var level = levels[0]; //[[],[],[]]
var block_arr = [];//0-0 2-3
var block_obj = {};

//b[2-3]={mark:0,open:0} 
//mark: -1为雷，0-8为数字块
//open：0未打开，1打开，-1标注为雷块，2标注为疑似雷块
var block_color = {
    block: '#369',
    open: '#ddd',
    mine: '#69d',
    highlight: '#89f',
    bomb: '#a00'
}
var icon = ['💣', '🚩', '❔', '💥']
var count = 0;
var mine_arr = []//雷坐标
var gameover = false;

g_init(0)
function g_init(n) {
    level = n == undefined ? level : levels[n];
    block_arr = [];
    mine_arr = [];
    count = 0;
    gameover = false;
    canvas.width = level[1] * 50;
    canvas.height = level[0] * 50;
    gnav.style.width = level[1] * 50 + 'px';
    mine_total.value = level[2];
    ctx.clearRect(0, 0, level[1] * 50, level[0] * 50)
    //初始化每个方块值
    for (let i = 0; i < level[0]; i++) {
        for (let j = 0; j < level[1]; j++) {
            let xy = j + "-" + i;
            block_arr.push(xy);
            block_obj[xy] = { mark: 0, open: 0 };
            //初始化布局:绘制游戏块
            drawBlock(xy, block_color.block);
        }
    }
    setMine()
}




//随机布雷
function setMine() {
    mine_arr = block_arr.sort(() => Math.random() - 0.5).slice(0, level[2])
    console.log(mine_arr)
    mine_arr.forEach(n => {
        block_obj[n].mark = -1;//mark为-1时为雷
        let around = getAround(n)
        around.forEach(xy => {
            if (block_obj[xy].mark != -1) {
                block_obj[xy].mark++;
            }
        })
    })
}

//showInfo()

//赋值显示方块信息
function showInfo() {
    block_arr.forEach(n => {
        if (block_obj[n].mark == -1) {
            drawBlock(n, block_color.mine)
        } else {
            markText(n, block_obj[n].mark)
        }
    })
}

//显示文本
function markText(xy, txt) {
    let [x, y] = xy.split('-').map(n => n * 50)
    ctx.save();
    ctx.font = '15px Arial';
    ctx.fillStyle = '#000';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(txt, x + 25, y + 25);
    ctx.restore();
}

//根据雷所在的位置，将其周围的值进行赋值，就无须每个遍历每个块记录雷值
//获取某个坐标的周边方块
function getAround(xy) {
    let [x, y] = xy.split('-').map(n => n * 1)
    let around = []
    for (let i = -1; i <= 1; i++) {
        for (let j = -1; j <= 1; j++) {
            let id = `${x + j}-${y + i}`
            if (block_arr.includes(id) && id != xy)
                around.push(id)
        }
    }
    return around
}

//绘制圆角矩形
function drawBlock(xy, c) {
    let w = 50;//width
    let r = 8;//radius
    let m = 2;//margin
    let [x, y] = xy.split('-').map(n => n * w)
    ctx.save()
    ctx.beginPath()
    ctx.moveTo(x, y + r)
    ctx.arcTo(x, y + w - m, x + w - m, y + w - m, r)
    ctx.arcTo(x + w - m, y + w - m, x + w - m, y, r)
    ctx.arcTo(x + w - m, y, x, y, r)
    ctx.arcTo(x, y, x, y + w - m, r)
    ctx.fillStyle = c
    ctx.fill()
    ctx.restore()
}

/**实现扫雷 鼠标事件 */ //click contextmenu
canvas.addEventListener('click', openBlock)
canvas.addEventListener('contextmenu', markMine)

function openBlock(ev) {
    if(gameover)return
    // 相对canvas的坐标
    let x = ~~(ev.offsetX / 50)
    let y = ~~(ev.offsetY / 50)
    let xy = x + '-' + y
    //打开游戏块：更新游戏数据，更新页面 
    block_obj[xy].open = 1
    drawBlock(xy, block_color.open)
    markText(xy, block_obj[xy].mark)//显示方块数字
    if (block_obj[xy].mark == 0) {
        //点到0，递归清零
        openZero(xy)
    } else if (block_obj[xy].mark == -1) {
        //点到雷，游戏结束
        drawBlock(xy, block_color.bomb)
        markText(xy, icon[0])
        markText(xy, icon[3])
        checkOver()
        //alert("挑战失败！")
    }
}

//递归清零的函数
function openZero(xy) {
    let around = getAround(xy)
    around.forEach(n => {
        if (block_obj[n].open == 0) {
            block_obj[n].open = 1
            drawBlock(n, block_color.open)
            markText(n, block_obj[n].mark)
            if (block_obj[n].mark == 0) {//若此时这个值还是0，继续调用此函数
                openZero(n)
            }
        }

    })
}

//右键标注小红旗
function markMine(ev) {
    //标注雷块：对未打开的块，标注雷快为-1，标注疑似雷快2，取消标注0
    ev.preventDefault();
    if(gameover)return
    let x = ~~(ev.offsetX / 50)
    let y = ~~(ev.offsetY / 50)
    let xy = x + '-' + y
    //更新数据，更新页面
    if (block_obj[xy].open == 0) {//未打开的，才可以标志
        block_obj[xy].open = -1;
        drawBlock(xy, block_color.mine)
        markText(xy, icon[1])
        count++
        mine_total.value = level[2] - count
        if (count == level[2]) {
            checkOver()
        }
    } else if (block_obj[xy].open == -1) {//若之前插上小红旗，则编程疑似
        block_obj[xy].open = 2
        drawBlock(xy, block_color.mine)
        markText(xy, icon[2])
        count--
        mine_total.value = level[2] - count
    } else if (block_obj[xy].open == 2) {//若之前为疑似，就进行清楚
        block_obj[xy].open = 0
        drawBlock(xy, block_color.block)
    }
}

//辅助扫雷：mousedown,mouseup
//1.按下鼠标，高亮周边，松开鼠标取消高亮
//2.辅助扫雷，对于明确的雷快或安全块进行标注或打开
//这个实现多个监听
canvas.addEventListener('mousedown', highlight)
canvas.addEventListener('mouseup', unhighlight)
canvas.addEventListener('mouseup', supGame)

function highlight(ev) {
    if(gameover)return
    let x = ~~(ev.offsetX / 50)
    let y = ~~(ev.offsetY / 50)
    let xy = x + '-' + y
    if (block_obj[xy].open != 1) {
        return
    }
    getAround(xy).forEach(n => {
        if (block_obj[n].open == 0) {
            drawBlock(n, block_color.highlight)
        }
    })
}

function unhighlight(ev) {
    let x = ~~(ev.offsetX / 50)
    let y = ~~(ev.offsetY / 50)
    let xy = x + '-' + y
    if (block_obj[xy].open != 1) {
        return
    }
    getAround(xy).forEach(n => {
        if (block_obj[n].open == 0) {
            drawBlock(n, block_color.block)
        }
    })
}

function supGame(ev) {
    if(gameover)return
    let x = ~~(ev.offsetX / 50)
    let y = ~~(ev.offsetY / 50)
    let xy = x + '-' + y
    if (block_obj[xy].open != 1) {
        return
    }
    let mark = block_obj[xy].mark
    let marked_mine = 0
    let unopen = 0
    let around = getAround(xy)
    around.forEach(n => {
        if (block_obj[n].open == -1)
            marked_mine++
        if (block_obj[n].open == 0)
            unopen++
    })
    around.forEach(n => {
        if (block_obj[n].open == 0)
            if (mark == marked_mine) {
                block_obj[n].open = 1
                drawBlock(n, block_color.open)
                markText(n, block_obj[n].mark)
                if (block_obj[n].mark == 0) {
                    openZero(n)
                }
                if (block_obj[n].mark == -1) {
                    drawBlock(n, block_color.bomb)
                    markText(n, icon[0])
                    markText(n, icon[3])
                    checkOver()
                }
            } else if ((mark - marked_mine) == unopen) {
                block_obj[n].open = -1
                drawBlock(n, block_color.mine)
                markText(n, icon[1])
                count++
                mine_total.value = level[2] - count
                if (count == level[2]) {
                    checkOver()
                }
            }
    })
}

/**游戏结束 */
function checkOver() {
    gameover = true;
    //every 返回true 或false
    let win = mine_arr.every(n => block_obj[n].mark == block_obj[n].open)
    // if (win == true) {
    //     setTimeout(() => {
    //         alert('恭喜胜利')
    //     }, 100)
    // } else {
    //     setTimeout(() => {
    //         alert('挑战失败')
    //     }, 100)
    // }
    setTimeout(() => {
        let next = confirm(win ? '恭喜胜利' : '挑战失败')
        if(next){
            g_init()
        }
    }, 100)
}



/**游戏主引擎 */



